package cn.agiledata.bank.linkbank.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import cn.agiledata.bank.common.dao.TransactionTemplate;
import cn.agiledata.bank.common.util.Constant;
import cn.agiledata.bank.common.util.DateUtil;
import cn.agiledata.bank.hibernateBean.Transaction;
import cn.agiledata.bank.linkbank.impl.UnsOrderImpl;
import cn.agiledata.bank.linkbank.logic.query.Order;
import cn.agiledata.bank.linkbank.logic.query.OrderQueryResponse;

/**
 * @author maxianbo
 * 
 */
public class UnsQueryServiceImpl implements UnsQueryService {
    private int maxQueryDays;

    private TransactionTemplate transactionTemplate;

    public void setMaxQueryDays(int maxQueryDays) {
        this.maxQueryDays = maxQueryDays;
    }

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    private boolean validTransStatus(String transStatus) {
        if (transStatus == null || transStatus.length() == 0)
            return true;
        String[] validTransStatuses = { Constant.TRANS_STATUS_WAITEBANKFEEDBACK,
                Constant.TRANS_STATUS_TRANSACTIONSUCCESS,
                Constant.TRANS_STATUS_TRANSACTIONFAIL };
        for (int i = 0; i < validTransStatuses.length; i++) {
            if (validTransStatuses[i].equals(transStatus))
                return true;
        }
        return false;
    }

    private Order getOrderByTransaction(Transaction trans) {
        UnsOrderImpl order = new UnsOrderImpl();
        order.setOrderId(trans.getOrderId());
        order.setUnsTransId(trans.getTransId());
        order.setCurrencyType(trans.getCurrency());
        order.setAmount(new BigDecimal(trans.getAmount().doubleValue()));
        order.setCreateTime(trans.getBeginDate());
        order.setStatus(trans.getTransStatus());
        order.setAssured(Constant.TRADE_TYPE_ASSURE
                .equals(trans.getTradeType()));
        order.setRemark(trans.getRemark());
        return order;
    }

    private OrderQueryResponse getOrderResultSet(List transactions, long total,
            int totalPage, int pageNo) {
        List orderList = new ArrayList();
        for (int i = 0; i < transactions.size(); i++) {
            Transaction trans = (Transaction) transactions.get(i);
            Order order = getOrderByTransaction(trans);
            orderList.add(order);
        }
        if (total == 0) {
            totalPage = 0;
            pageNo = 0;
        }
        Order[] orders = (Order[]) orderList.toArray(new Order[0]);
        return OrderQueryResponse.getSuccessfulResponse(total, totalPage,
                pageNo, orders);
    }

    public OrderQueryResponse queryOrdersByOrderIdRange(String accountId,
            String beginOrderId, String endOrderId, String transStatus,
            int maxPerPage, int pageNo) {
        if (!validTransStatus(transStatus)) {
            return OrderQueryResponse.getFailedResponse(
                    OrderQueryResponse.RETURN_CODE_INVALID_TRANSSTATUS, null);
        }
        if (maxPerPage < 0)
            maxPerPage = 0;
        if (pageNo < 1)
            pageNo = 1;
        long total = this.transactionTemplate
                .getTransactionsTotalByOrderIdRange(accountId, beginOrderId,
                        endOrderId, transStatus);
        List transactions = this.transactionTemplate
                .getTransactionsByOrderIdRange(accountId, beginOrderId,
                        endOrderId, transStatus, maxPerPage, pageNo);
        return getOrderResultSet(transactions, total, (int) total / maxPerPage,
                pageNo);
    }

    private boolean appropriateTimeRange(Date beginTime, Date endTime) {
        if (this.maxQueryDays <= 0)
            return true;
        return DateUtil.naturalDaysBetween(beginTime, endTime) <= this.maxQueryDays;
    }

    public OrderQueryResponse queryOrdersByTimeRange(String accountId,
            Date beginTime, Date endTime, String transStatus, int maxPerPage,
            int pageNo) {
        if (!validTransStatus(transStatus)) {
            return OrderQueryResponse.getFailedResponse(
                    OrderQueryResponse.RETURN_CODE_INVALID_TRANSSTATUS, null);
        }
        if (beginTime.after(endTime)) {
            return OrderQueryResponse.getFailedResponse(
                    OrderQueryResponse.RETURN_CODE_BEGINTIME_AFTER_ENDTIME,
                    null);
        }
        if (!appropriateTimeRange(beginTime, endTime)) {
            return OrderQueryResponse.getFailedResponse(
                    OrderQueryResponse.RETURN_CODE_OVERLONG_TIME_RANGE, null);
        }
        if (maxPerPage < 0)
            maxPerPage = 0;
        if (pageNo < 1)
            pageNo = 1;
        long total = this.transactionTemplate.getTransactionsTotalByTimeRange(
                accountId, beginTime, endTime, transStatus);
        List transactions = this.transactionTemplate
                .getTransactionsByTimeRange(accountId, beginTime, endTime,
                        transStatus, maxPerPage, pageNo);
        return getOrderResultSet(transactions, total, (int) total / maxPerPage,
                pageNo);
    }

}
